<!-- 业务详情 -->
<template>
	<div class="app-container">
		<div class="overview-box">
			<div class="overview-title">
				<div class="circle"></div>
				<span class="title-label">用户操作详情</span>
			</div>

			<el-row class="overview-row">
				<el-col :span="6">
					<span class="overview-label">详单编号：</span>
					<span class="overview-text">{{ businessDetailData.docId }}</span>
				</el-col>
				<el-col :span="6"> </el-col>
				<el-col :span="5">
					<span class="overview-label">操作系统：</span>
					<span class="overview-text">{{ businessDetailData.browser }}</span>
				</el-col>
				<el-col :span="6">
					<span class="overview-label">浏览器：</span>
					<span class="overview-text">{{ businessDetailData.operatingSystem }}</span>
				</el-col>
			</el-row>
			<el-row class="overview-row">
				<el-col :span="6">
					<span class="overview-label">业务系统：</span>
					<span class="overview-text">{{ businessDetailData.systemName }}</span>
				</el-col>
				<el-col :span="6">
					<span class="overview-label">开始时间：</span>
					<span class="overview-text">{{ businessDetailData.startTime }}</span>
				</el-col>
				<el-col :span="5">
					<span class="overview-label">办理时长：</span>
					<span class="overview-text">{{ formatDealTime }}</span>
				</el-col>
				<el-col :span="6">
					<span class="overview-label">网络传输耗时：</span>
					<span class="overview-text">{{ formatNetTranslateTime }}</span>
				</el-col>
			</el-row>
			<el-row class="overview-row">
				<el-col :span="6">
					<span class="overview-label">业务名称：</span>
					<span class="overview-text">{{ businessDetailData.businessName }}</span>
				</el-col>
				<el-col :span="6">
					<span class="overview-label">结束时间：</span>
					<span class="overview-text">{{ businessDetailData.endTime }}</span>
				</el-col>
				<el-col :span="5">
					<span class="overview-label">响应时长：</span>
					<span class="overview-text">{{ formatServerResponseTime }}</span>
				</el-col>
				<el-col :span="6">
					<span class="overview-label">客户端空闲时长：</span>
					<span class="overview-text">{{ formatClientFreeTime }}</span>
				</el-col>
			</el-row>
			<el-row class="overview-row">
				<el-col :span="22" style="word-break: break-all">
					<span class="overview-label">专属指标：</span>
					<span class="overview-text">{{ businessDetailData.exclusiveIndicator }}</span>
				</el-col>
				<el-col :span="2" style="text-align: center">
					<el-link icon="el-icon-document-copy" :underline="false" style="color: #ffffff" @click="copyIndicator">复制</el-link>
				</el-col>
			</el-row>
		</div>

		<div class="container-bg">
			<div class="overview-title">
				<div class="circle"></div>
				<span class="title-label">业务步骤</span>
			</div>
			<YdTable
				:formData="formData"
				:tableConfig="tableConfig"
				:tableData="tableData.data"
				ref="busiStepTableRef"
				@sizeChangeHandler="searchHandler"
				@currentChangeHandler="searchHandler"
				@sortChangeHandler="searchHandler"
				@expandRowHandler="expandRowHandler"
			>
				<!-- 告警数展开列表 -->
				<template #expand="props">
					<YdTable
						:formData="alarmFormData"
						:tableConfig="alarmTableConfig"
						:tableData="alarmTableData[props.data.id].data"
						@sortChangeHandler="searchDetailHandler"
					></YdTable>
				</template>
			</YdTable>
		</div>

		<div class="container-bg" v-if="is_Itshow">
			<div class="overview-title">
				<div class="circle"></div>
				<span class="title-label">业务步骤IT路径图</span>
			</div>
			<yd-it-road
				v-if="is_Itshow"
				v-loading="e2eRelationConfig.loading"
				ref="ydItRoadRef"
				:config="{ type: 'StepEndToEndRelation', canvasHeight: 400, noDataFlag: false, customOptions: e2eRelationConfig.customOptions }"
				@dblclickNode="dblclickNodeHandler"
				@dragNode="updateSegmentPos"
			></yd-it-road>
		</div>

		<div class="container-bg" style="margin-bottom: 10px">
			<div class="overview-title">
				<div class="circle"></div>
				<span class="title-label">节点信息</span>
			</div>
			<YdTable
				:formData="e2eDetail.formData"
				:tableConfig="e2eDetail.tableConfig"
				:tableData="e2eDetail.tableData.data"
				@sizeChangeHandler="searchNodeInfo"
				@currentChangeHandler="searchNodeInfo"
				@sortChangeHandler="searchNodeInfo"
				ref="busiStepTableRef1"
				@expandRowHandler="expandRowHandler1"
			>
				<!-- 告警数展开列表 -->
				<template #expand="props">
					<YdTable
						:formData="alarmFormData1"
						:tableConfig="alarmTableConfig1"
						:tableData="alarmTableData1[props.data.id].data"
						@sortChangeHandler="searchDetailHandler1"
					></YdTable>
				</template>
			</YdTable>
		</div>

		<!-- 网络详情  -->
		<yd-card style="margin-bottom: 10px">
			<div class="yd-card-header yd-flex">
				<div class="yd-flex1">
					<div class="yd-circle"></div>
					<span class="yd-card-title">网络信息</span>
				</div>
			</div>
			<YdTable
				:formData="formData"
				:tableConfig="networkDetailConfig"
				:tableData="networkDetailData.data"
				@sizeChangeHandler="queryNetworkDetail"
				@currentChangeHandler="queryNetworkDetail"
				@sortChangeHandler="queryNetworkDetail"
			></YdTable>
		</yd-card>

		<!-- 网元详情  -->
		<yd-card style="margin-bottom: 10px">
			<div class="yd-card-header yd-flex">
				<div class="yd-flex1">
					<div class="yd-circle"></div>
					<span class="yd-card-title">网元详情</span>
				</div>
			</div>
			<YdTable
				:formData="formData"
				:tableConfig="networkMetaDataDetailConfig"
				:tableData="networkMetaDataDetailData.data"
				@sizeChangeHandler="queryNetworkMetaDataDetail"
				@currentChangeHandler="queryNetworkMetaDataDetail"
				@sortChangeHandler="queryNetworkMetaDataDetail"
			></YdTable>
		</yd-card>
	</div>
</template>
<script setup name="bpmBusinessDetail" lang="tsx">
import { onActivated, onMounted, computed, ref, reactive, getCurrentInstance, shallowRef, nextTick, onDeactivated } from 'vue';
import { useRoute } from 'vue-router';
import {
	queryBusinessDetailByDetailId,
	queryBusinessStepListPage,
	stepEndToEndRelation,
	queryEndToEndDetail,
	updateSegmentPosition,
	queryNetworkDetailList,
} from '@/api/bpm/business/business_detail';
import { getBaseAlarmList } from '@/api/bpm/alarm/busi_detail_alarm';
import { getConfigKey } from '@/api/management/systemManage/systemConfig';
import YdItRoad from '@/components/YdItRoad/index.vue';
import YdTable from '@/components/YdTable/index.vue';
import { copyMsg, toDecimalFormate, parseTime, getLastNodeArr, simulateFormSubmit, formatBytes } from '@/utils/common';
import { formatdataforBps, BpsConversion, formatdataforByte, formatdataforPps } from '@/utils/metaData';
import { GraphCustomOptionsType, GraphData, NodeConfigType } from '@/components/YdItRoad/itRoad-type';
import useIsParamsChange from '@/components/YdForm/useIsParamsChange';
import { queryNetworkMetaDataDetailList } from '@/api/bpm/network-detail/index';

const instance = getCurrentInstance();
const proxy = instance?.proxy;

const route = useRoute();

let formatDealTime = computed(() => {
	return toDecimalFormate(businessDetailData.value.dealTime, 'wm');
});
let formatServerResponseTime = computed(() => {
	return toDecimalFormate(businessDetailData.value.serverResponseTime, 'wm');
});

let formatNetTranslateTime = computed(() => {
	return toDecimalFormate(parseInt(businessDetailData.value.clientTranslateTime) + parseInt(businessDetailData.value.serverTranslateTime), 'wm');
});
let formatClientFreeTime = computed(() => {
	return toDecimalFormate(businessDetailData.value.clientFreeTime, 'wm');
});
// 用户获取dom
let busiStepTableRef = shallowRef<InstanceType<typeof YdTable>>();
let busiStepTableRef1 = shallowRef<InstanceType<typeof YdTable>>();
let ydItRoadRef = shallowRef<InstanceType<typeof YdItRoad>>();

// 搜索表单数据
let is_Itshow = ref(true);
let formData = reactive<FormModelType>({
	pageNum: 1,
	pageSize: 10,
});

// 列表配置
let tableConfig = reactive<TableConfigType>({
	columns: [
		{
			label: '步骤类型',
			prop: 'stepType',
			width: 80,
		},
		{
			label: '步骤名称',
			prop: 'stepName',
		},
		{
			label: '响应状态',
			prop: 'dealState',
			width: 80,
			formatter(row: any, val: any) {
				if (val === 1) {
					return '成功';
				}
				return '失败';
			},
		},
		{
			label: '自定义返回码',
			prop: 'customResCode',
			width: 110,
			render: (row, val) => {
				/* eslint-disable */
				if (row.explain == undefined || row.explain == null || row.explain == '') {
					return <span>{val}</span>;
				} else {
					return (
						<span>
							{val}({row.explain})
						</span>
					);
				}
			},
		},
		{
			label: '告警数',
			prop: 'alarmCount',
			width: 90,
			operation: [
				{
					text: undefined,
					rowKey: 'alarmCount',
					handler: (scope) => handleClickAlarm(scope.row),
				},
			],
		},
		{
			label: '请求开始时间',
			prop: 'startTime',
		},
		{
			label: '响应结束时间',
			prop: 'endTime',
		},
		{
			label: '处理时长',
			prop: 'dealTime',
			width: 100,
			formatter(row: any, val: any) {
				return toDecimalFormate(val, 'wm');
			},
		},
		{
			label: '响应时长',
			prop: 'serverResponseTime',
			width: 100,
			formatter(row: any, val: any) {
				return toDecimalFormate(val, 'wm');
			},
		},
		{
			label: '网络传输耗时',
			prop: '',
			width: 120,
			formatter(row: any, val: any) {
				let a: number = (row.clientTranslateTime as number) || 0;
				let b: number = (row.serverTranslateTime as number) || 0;
				let res = a + b;
				return toDecimalFormate(res, 'wm');
			},
		},
		{
			label: '请求IP端口',
			prop: 'requestIp',
			formatter(row: any, val: any) {
				return val + ':' + row.requestPort;
			},
		},
		{
			label: '响应IP端口',
			prop: 'responsePort',
			formatter(row: any, val: any) {
				return row.responseIp + ':' + row.responsePort;
			},
		},
		{
			label: '请求大小',
			prop: 'requestBytes',
			formatter: (row: any, val: any) => {
				return formatByteData(val);
			},
		},
		{
			label: '响应大小',
			prop: 'responseBytes',
			formatter: (row: any, val: any) => {
				return formatByteData(val);
			},
		},
		{
			label: 'IT路径图',
			prop: '',
			width: 100,
			render: (row: any, val: any) => {
				let isActive = row.businessStepDataId === e2eRelationConfig.preRelvanceId;
				let o = {
					systemId: row.systemId,
					preRelvanceId: row.businessStepDataId,
					type: 2,
					resourceCode: row.resourceCode,
					startTimeUsec: formData.startTimeUsec,
					endTimeUsec: formData.endTimeUsec,
					id: row.id,
					is_Itshow: row.is_Itshow,
					businessCode: row.businessCode,
					stepCode: row.stepCode,
				};
				return (
					<div onClick={() => renderEndToEndRelation(o)} style={row.is_Itshow ? 'cursor: pointer; color: #2beded;' : 'cursor: pointer;'}>
						<svg-icon icon-class={row.is_Itshow ? 'eye-open' : 'eye'} style="margin-right: 6px;"></svg-icon>
					</div>
				);
			},
		},
	],
	pagination: {
		pageNum: 1,
	},
	loading: true,
	expandHide: true,
});
// 列表数据
let tableData = reactive<anyObj>({
	data: [],
});
// 告警数展开列表表单数据
let alarmFormData = reactive<FormModelType>({
	systemId: null,
	relvanceDataId: '',
	startTime: '',
	endTime: '',
});
// 告警数展开列表配置
let alarmTableConfig = reactive<TableConfigType>({
	columns: [
		{
			label: '告警对象',
			prop: 'alarmObject',
			align: 'center',
			width: 320,
		},
		{
			label: '告警级别',
			prop: 'alarmLevelName',
			align: 'center',
			width: 90,
		},
		{
			label: '告警现象',
			prop: 'alarmContext',
			align: 'center',
			width: 380,
		},
		{
			label: '告警类型',
			prop: 'alarmIndicatorName',
			align: 'center',
			width: 120,
		},
		{
			label: '返回码',
			prop: 'alarmResultCode',
			align: 'center',
			width: 80,
		},
		{
			label: '告警时间',
			prop: 'alarmTriggerTime',
			align: 'center',
			sortable: true,
			width: 170,
		},
		{
			label: '专属指标',
			prop: 'exclusiveIndicator',
			align: 'center',
		},
	],
	pagination: {
		pageNum: 1,
	},
	loading: true,
});
// 告警数展开列表数据
let alarmTableData = reactive<anyObj>({
	data: [],
});
// 告警数展开列表表单数据
let alarmFormData1 = reactive<FormModelType>({
	systemId: null,
	relvanceDataId: '',
	startTime: '',
	endTime: '',
});
// 告警数展开列表配置
let alarmTableConfig1 = reactive<TableConfigType>({
	columns: [
		{
			label: '告警对象',
			prop: 'alarmObject',
			align: 'center',
			width: 320,
		},
		{
			label: '告警级别',
			prop: 'alarmLevelName',
			align: 'center',
			width: 90,
		},
		{
			label: '告警现象',
			prop: 'alarmContext',
			align: 'center',
			width: 380,
		},
		{
			label: '告警类型',
			prop: 'alarmIndicatorName',
			align: 'center',
			width: 120,
		},
		{
			label: '返回码',
			prop: 'alarmResultCode',
			align: 'center',
			width: 80,
		},
		{
			label: '告警时间',
			prop: 'alarmTriggerTime',
			align: 'center',
			sortable: true,
			width: 170,
		},
		{
			label: '专属指标',
			prop: 'exclusiveIndicator',
			align: 'center',
		},
	],
	pagination: {
		pageNum: 1,
	},
	loading: true,
	expandHide: true,
});
// 告警数展开列表数据
let alarmTableData1 = reactive<anyObj>({
	data: [],
});

// 网络详情表格配置
let networkDetailConfig = reactive<TableConfigType>({
	columns: [
		{
			label: '请求IP端口',
			prop: 'requestIp',
			width: 140,
			formatter(row: any) {
				return row.requestIp + ':' + row.requestPort;
			},
		},
		{
			label: '响应IP端口',
			prop: 'responseIp',
			width: 140,
			formatter(row: any) {
				return row.responseIp + ':' + row.responsePort;
			},
		},
		{
			label: '字节数',
			prop: 'bytes',
			formatter(row: any, val: any) {
				return formatdataforByte(val);
			},
		},
		{
			label: '字节率',
			prop: 'byteRate',
			formatter(row: any, val: any) {
				return BpsConversion(val);
			},
		},
		{
			label: '包数',
			prop: 'packets',
		},
		{
			label: '包率',
			prop: 'packetRate',
			formatter(row: any, val: any) {
				return formatdataforPps(val);
			},
		},
		{
			label: '比特率',
			prop: 'bitRate',
			formatter(row: any, val: any) {
				return formatdataforBps(val);
			},
		},
		{
			label: '重传率',
			prop: 'retryRate',
			formatter(row: any, val: any) {
				return val + '%';
			},
		},
		{
			label: '重传包数',
			prop: 'retryPackets',
		},
		{
			label: '建连失败数',
			prop: 'connectFail',
		},
		{
			label: '建连耗时',
			prop: 'connectTime',
			formatter(row: any, val: any) {
				return toDecimalFormate(val, 'wm');
			},
		},
		{
			label: '服务器响应时间',
			prop: 'serverResponseTime',
			width: 100,
			formatter(row: any, val: any) {
				return toDecimalFormate(val, 'wm');
			},
		},
		{
			label: '数据传输时间',
			prop: 'networkTime',
			formatter(row: any, val: any) {
				return toDecimalFormate(val, 'wm');
			},
		},
		{
			label: '请求开始时间',
			prop: 'startTime',
			width: 140,
		},
		{
			label: '响应结束时间',
			prop: 'endTime',
			width: 145,
		},
	],
	loading: false,
	disableOrderNumber: true,
	pagination: {
		pageNum: 1,
	},
});
// 网络信息表格数据
let networkDetailData = reactive({
	data: [],
});

// 网元详情表格配置
let networkMetaDataDetailConfig = reactive<TableConfigType>({
	columns: [
		{
			label: 'CPU使用率',
			prop: 'cpuRate',
			sortable: true,
			formatter(row: any, value: any) {
				return value + '%';
			},
		},
		{
			label: '内存使用率',
			prop: 'memoryRate',
			sortable: true,
			formatter(row: any, value: any) {
				return value + '%';
			},
		},
		{
			label: '磁盘IO',
			prop: 'diskRate',
			sortable: true,
			formatter(row: any, value: any) {
				return value + '%';
			},
		},
		{
			label: '系统负载',
			prop: 'sysWork',
			sortable: true,
			formatter(row: any, value: any) {
				return value + '秒';
			},
		},
		{
			label: '磁盘smart',
			prop: 'diskSmart',
			sortable: true,
			formatter(row: any, value: any) {
				return value + '秒';
			},
		},
		{
			label: '网卡流量',
			prop: 'networkFlow',
			sortable: true,
			formatter(row: any, value: any) {
				return formatBytes(value);
			},
		},
	],
	loading: false,
	disableOrderNumber: true,
	pagination: {
		pageNum: 1,
	},
});
// 网元详情表格数据
let networkMetaDataDetailData = reactive({
	data: [],
});

// 告警数展开列表对应的步骤id
let tempSysProcessId = ref('');
// 业务详单数据
let businessDetailData = ref<anyObj>({
	// 详单编号
	docId: '',
	// 系统名称
	systemName: '',
	// 业务名称
	businessName: '',
	// 开始时间
	startTime: '',
	// 结束时间
	endTime: '',
	// 办理时长
	dealTime: '',
	// 响应时长
	serverResponseTime: '',
	// 客户端传输时长
	clientTranslateTime: '',
	// 服务端传输时长
	serverTranslateTime: '',
	// 客户端空闲时长
	clientFreeTime: '',
	// 专属指标
	exclusiveIndicator: '',
});
// 端到端关联图配置
let e2eRelationConfig = reactive<anyObj>({
	loading: false,
	mode: 'default',
	preRelvanceId: undefined,
	firstLoad: true,
	customOptions: {
		maxZoom: 1.5,
		layout: {
			type: 'dagre',
			rankdir: 'LR',
			nodesep: 60,
			ranksep: 110,
		},
		modes: {
			// 默认模式
			defaultMode: [
				// 节点高亮(自定义)
				'activate-node',
			],
		},

		// 工具按钮
		toolbarObj: {
			getContent: () => {
				let outDiv = document.createElement('div');
				outDiv.style.width = '120px';
				outDiv.innerHTML = `<ul>
                    <li code="edit"><i id="iconEditId" class="el-icon-edit-outline"></i></li>
                  </ul>`;
				return outDiv;
			},
			handleClick: (code: any, graph: any) => {
				if (code === 'edit') {
					if (e2eRelationConfig.mode === 'default') {
						e2eRelationConfig.mode = 'edit';
						document.getElementById('iconEditId')!.style.color = '#2beded';
					} else {
						e2eRelationConfig.mode = 'default';
						document.getElementById('iconEditId')!.style.color = '#ffffff';
					}
					ydItRoadRef.value?.setGraphMode(e2eRelationConfig.mode);
				}
			},
		},
	},
});
// 端到端节点详情
let e2eDetail = reactive<anyObj>({
	// 搜索表单数据
	formData: {
		pageNum: 1,
		pageSize: 10,
	},
	// 列表配置
	tableConfig: {
		columns: [
			{
				label: '业务资源',
				prop: 'resource',
			},
			{
				label: '请求IP端口',
				prop: 'requestIp',
				width: 160,
				formatter(row: any, val: any) {
					return row.requestIp + ':' + row.requestPort;
				},
			},
			{
				label: '响应IP端口',
				prop: 'responseIp',
				width: 160,
				formatter(row: any, val: any) {
					return row.responseIp + ':' + row.responsePort;
				},
			},
			{
				label: '系统返回码',
				prop: 'serverResCode',
				width: 90,
			},
			{
				label: '业务状态',
				prop: 'dealState',
				width: 80,
				formatter(row: any, val: any) {
					if (val === 1) {
						return '成功';
					}
					return '失败';
				},
			},
			{
				label: '响应时长',
				prop: 'serverResponseTime',
				width: 90,
				formatter(row: any, val: any) {
					return toDecimalFormate(val, 'wm');
				},
			},
			{
				label: '请求开始时间',
				prop: 'startTime',
			},
			{
				label: '响应结束时间',
				prop: 'endTime',
			},
			{
				label: '处理时长',
				prop: 'dealTime',
				width: 90,
				formatter(row: any, val: any) {
					return toDecimalFormate(val, 'wm');
				},
			},
			{
				label: '请求大小',
				prop: 'requestBytes',
				formatter(row: any, val: any) {
					return formatByteData(val);
				},
			},
			{
				label: '响应大小',
				prop: 'responseBytes',
				formatter(row: any, val: any) {
					return formatByteData(val);
				},
			},
			{
				label: '客户端网络传输时长',
				prop: 'clientTranslateTime',
				width: 90,
				formatter(row: any, val: any) {
					return toDecimalFormate(val, 'wm');
				},
			},
			{
				label: '服务端网络传输时长',
				prop: 'serverTranslateTime',
				width: 90,
				formatter(row: any, val: any) {
					return toDecimalFormate(val, 'wm');
				},
			},
			{
				label: '告警量',
				prop: 'alarmCount',
				width: 80,
				operation: [
					{
						text: undefined,
						rowKey: 'alarmCount',
						handler: (scope: any) => handleClickAlarm1(scope.row),
					},
				],
			},
			{
				label: '专属指标',
				prop: 'exclusiveIndicator',
			},
			{
				label: '操作',
				prop: '',
				operation: [
					{
						text: '提包分析',
						handler: (scope: any) => {
							handlePackageAnalysis(scope.row, 1);
						},
					},
					{
						text: '数据包下载',
						handler: (scope: any) => {
							handlePackageAnalysis(scope.row, 2);
						},
					},
				],
				width: 170,
				hide: false,
			},
		],
		pagination: {
			pageNum: 1,
			total: 0,
		},
		loading: true,
		expandHide: true,
		alarmType: true,
	},
	// 列表数据
	tableData: {
		data: [],
		total: 0,
	},
});
// 系统id
let tempSystemId = ref(undefined);
// 当前选中端首端标识(默认首端)
let currentHeaderFlag = ref(1);

// 是否展示提包分析相关按钮
let showTibao = ref(false);
let currentRow = ref();
let currentRow1 = ref();
let currentStepData = ref(); //业务步骤的第一个数据
let currentNode = ref(); //业务步骤it路径图当前节点

const { isParamsChange } = useIsParamsChange(route.query); //query是否改变
onMounted(() => {
	getConfigKey('apm.datapacket.analysis.button.show').then((res: ApiResponse) => {
		if (res.code === 0) {
			showTibao.value = res.data === 'true' ? true : false;
			e2eDetail.tableConfig.columns.find((col: any) => col.label === '操作').hide = !showTibao;
		}
	});
});
onActivated(() => {
	// if (isParamsChange(route.query)) {
	initQuery(route.query, formData);
	// 渲染业务详情
	renderDetailInfo();
	// 搜索业务步骤列表
	searchHandler();
	// }
});
onDeactivated(() => {
	closeExpand();
});
// 关闭展开行
function closeExpand() {
	busiStepTableRef.value?.toggleRowExpansion(currentRow.value, false);
	busiStepTableRef1.value?.toggleRowExpansion(currentRow1.value, false);
}
// 格式化传过来的参数
function initQuery(query: anyObj, formData: FormModelType) {
	try {
		let data = JSON.parse(query.data);
		for (let key in data) {
			formData[key] = data[key];
		}
	} catch {
		for (let key in query) {
			formData[key] = query[key];
		}
	}
}
function formatByteData(data: any) {
	if (Number(data) > 1024 * 1024) {
		return (data / 1024 / 1024).toFixed(2) + 'MB';
	}
	if (Number(data) > 1024) {
		return (data / 1024).toFixed(2) + 'KB';
	}
	return data + 'B';
}
// 渲染业务详情
function renderDetailInfo() {
	queryBusinessDetailByDetailId({
		businessDetailId: formData.businessDetailId,
		startTime: formData.startTime,
		endTime: formData.endTime,
	}).then((res) => {
		if (res.code !== 0) {
			return;
		}
		if (res.data instanceof Object) {
			businessDetailData.value = res.data;
		}
	});
}
// 复制专属指标
function copyIndicator() {
	if (copyMsg(businessDetailData.value.exclusiveIndicator)) {
		proxy?.$message.success('专属指标复制成功');
	}
}
// 搜索
function searchHandler() {
	tableConfig.loading = true;
	queryBusinessStepListPage(formData).then((res: ApiResponse) => {
		tableConfig.loading = false;
		if (res.code !== 0) {
			return;
		}

		tableData.data = res.data.data;
		// tableData.total = res.data.total;
		tableConfig.pagination!.total = res.data.total;

		// total小于10不展示分页栏
		// if (tableData.total <= 10) {
		// 	tableConfig.pagination = false;
		// } else {
		// 	tableConfig.pagination = true;
		// }
		for (let i of res.data.data) {
			i.is_Itshow = false;
		}
		if (res.data.data[0] != undefined) {
			res.data.data[0].is_Itshow = true;
		}
		e2eDetail.tableConfig.loading = false;
		e2eDetail.tableData.data = [];
		e2eDetail.tableData.total = 0;
		// 如果有数据，默认展示第一条步骤的端到端关联图
		// e2eRelationConfig.firstLoad
		if (tableData.data.length > 0) {
			let firstData: anyObj = tableData.data[0];
			tempSystemId.value = firstData.systemId;
			currentStepData.value = firstData;
			renderEndToEndRelation({
				systemId: firstData.systemId,
				preRelvanceId: firstData.businessStepDataId,
				type: 2,
				resourceCode: firstData.resourceCode,
				startTimeUsec: formData.startTimeUsec,
				endTimeUsec: formData.endTimeUsec,
				businessCode: firstData.businessCode,
				stepCode: firstData.stepCode,
			});
			e2eRelationConfig.firstLoad = false;
		}
		// 初始化告警数展开列表
		tableData.data.forEach((ov: any) => {
			if (!alarmTableData[ov.id]) {
				alarmTableData[ov.id] = {
					data: [],
					total: 0,
				};
			} else {
				alarmTableData[ov.id] = {
					data: [],
					total: 0,
				};
			}
		});
	});
}
// 业务步骤表格点击告警数展开表格
function handleClickAlarm(row: any) {
	busiStepTableRef.value?.toggleRowExpansion(row);
	currentRow.value = row;
}
// 展开行查询告警数列表
function expandRowHandler(row: any) {
	tempSysProcessId.value = row.id;
	alarmFormData.systemId = row.systemId;
	alarmFormData.relvanceDataId = row.businessStepDataId;
	alarmFormData.startTime = parseTime(row.startTime, '{y}-{m}-{d} {h}:{i}') + ':00';
	alarmFormData.endTime = parseTime(row.endTime, '{y}-{m}-{d} {h}:{i}') + ':00';
	searchDetailHandler();
}
// 获取告警数列表数据
function searchDetailHandler() {
	alarmTableConfig.loading = true;
	getBaseAlarmList({
		...alarmFormData,
		headerFlag: currentHeaderFlag.value,
		alarmIndicatorIds: [],
		alarmLevelIds: [],
		alarmStates: [],
		businessCodes: [],
		pageNum: 1,
		pageSize: 999,
		segmentIds: [],
		stepCodes: [],
	}).then((res: ApiResponse) => {
		alarmTableConfig.loading = false;
		if (res.code !== 0) {
			return;
		}
		console.log('tempSysProcessId', tempSysProcessId.value);
		alarmTableData[tempSysProcessId.value].data = res.data.data;
		alarmTableConfig.pagination!.total = res.data.total;
	});
}
function handleClickAlarm1(row: any) {
	currentRow1.value = row;
	busiStepTableRef1.value?.toggleRowExpansion(row);
}
function expandRowHandler1(row: any) {
	tempSysProcessId.value = row.id;
	alarmFormData1.relvanceDataId = row.idStr;
	alarmFormData1.systemId = 1;
	alarmFormData1.startTime = parseTime(row.startTime, '{y}-{m}-{d} {h}:{i}') + ':00';
	alarmFormData1.endTime = parseTime(row.endTime, '{y}-{m}-{d} {h}:{i}') + ':00';
	searchDetailHandler1();
}

// 获取告警数列表数据
function searchDetailHandler1() {
	console.log('searchDetailHandler1');
	let req = {
		alarmIndicatorIds: [],
		alarmLevelIds: [],
		alarmStates: [],
		businessCodes: [],
		category: 'BPM',
		endTime: alarmFormData1.endTime,
		headerFlag: currentHeaderFlag.value,
		pageNum: 1,
		pageSize: 999,
		relvanceDataId: alarmFormData1.relvanceDataId,
		segmentIds: [],
		startTime: alarmFormData1.startTime,
		stepCodes: [],
		systemId: tempSystemId.value,
	};

	alarmTableConfig1.loading = true;
	getBaseAlarmList(req).then((res: ApiResponse) => {
		alarmTableConfig1.loading = false;
		if (res.code !== 0) {
			return;
		}
		console.log('alarmTableData1-', alarmTableData1);
		alarmTableData1[tempSysProcessId.value].data = res.data.data;
		// alarmTableData1[tempSysProcessId.value].total = res.data.total;
		alarmTableConfig1.pagination!.total = res.data.total;
		console.log('alarmTableData1', alarmTableData1);
		// alarmTableData1[tempSysProcessId.value] = {
		//   data: res.data.data,
		//   total: res.data.total,
		// }
	});
}

// 渲染端到端关联图
function renderEndToEndRelation(o: any) {
	if (o.id == undefined) {
		tableData.data[0].is_Itshow = true;
		is_Itshow.value = true;
	} else {
		for (let j of tableData.data) {
			if (j.id == o.id && o.is_Itshow == false) {
				j.is_Itshow = true;
				is_Itshow.value = true;
			} else if (j.id == o.id && o.is_Itshow == true) {
				j.is_Itshow = false;
				is_Itshow.value = false;
				tableData.data = JSON.parse(JSON.stringify(tableData.data));
				return;
			} else {
				j.is_Itshow = false;
			}
		}
	}
	e2eRelationConfig.loading = true;
	o.id = undefined;
	o.is_Itshow = undefined;
	o.detailId = formData.businessDetailId;
	stepEndToEndRelation(o).then((res: ApiResponse) => {
		let d: GraphData = {
			nodes: [],
			edges: [],
		};
		e2eRelationConfig.loading = false;
		// 清除画布
		ydItRoadRef.value?.graph.clear();
		if (res.code !== 0) {
			// 接口异常
			return;
		}
		e2eRelationConfig.preRelvanceId = o.preRelvanceId;
		e2eRelationConfig.startTimeUsec = o.startTimeUsec;
		e2eRelationConfig.endTimeUsec = o.endTimeUsec;

		if (res.data.length <= 0) {
			// 无数据
			return;
		}

		let isSavePos = true;
		// 将布局方式还原为默认
		// ydItRoadRef.value?.setLayout(e2eRelationConfig.customOptions.layout);
		// 临时节点数组
		let tempNodes = [];
		// 不进行展示的端id数组
		let noShowIdList = [];
		formatGraphData(res.data);
		function formatGraphData(arr: any[], idKey = 'segmentId') {
			if (arr instanceof Array === false) {
				console.error('arr不是数组---------');
				return;
			}
			arr.forEach((node: any) => {
				node.id = node[idKey] + '';
				if (node.locationX) {
					// 采用自定义布局
					isSavePos = false;
					ydItRoadRef.value?.setLayout({
						type: 'stepAnalysisLayout',
					});
				}

				let index = d.nodes.findIndex((n) => n.id === node[idKey]);
				// 没有的节点才加进去
				if (index === -1 && node.show) {
					// 设置x、y坐标
					d.nodes.push(dealNodeData(node));
				}
				if (node.childNodes instanceof Array) {
					node.childNodes.forEach((subNode: any) => {
						d.edges.push({
							source: node[idKey] + '',
							target: subNode[idKey] + '',
							sourceAnchor: 2,
							targetAnchor: 0,
							label: node.clientTransTime,
							labelCfg: {
								refY: 10,
								style: {
									fill: '#ffffff',
								},
							},
						});
					});
					formatGraphData(node.childNodes);
				}
			});
		}

		console.log('d', d);

		// 去掉最后一端的请求后端开始时间、后端响应结束时间、后端处理时长
		let lastNodeArr = getLastNodeArr(d.edges, d.nodes);
		// console.log("lastNodeArr",lastNodeArr)
		lastNodeArr.forEach((item: any) => {
			item.indicatorText = item.lastIndicatorText;
			item.indicatorValText = item.lastIndicatorValText;
		});
		// 渲染关联图
		ydItRoadRef.value?.loadItRoadData(d);
		// 判断是否保存端位置
		if (isSavePos) {
			let nodes = ydItRoadRef.value?.getAllNodes();
			nodes.forEach((node: any) => {
				let model = node.getModel();
				updateSegmentPos(null, {
					segmentId: model.id,
					locationX: model.x,
					locationY: model.y,
				});
			});
		}
		// 默认展示第一个节点信息
		if (d.nodes.length > 0) {
			// 默认当前选中端首端标识为1
			currentHeaderFlag.value = 1;
			e2eDetail.formData = {
				...e2eDetail.formData,
				dataType: d.nodes[0].info.dataType,
				dataId: d.nodes[0].info.dataId,
				codeList: d.nodes[0].info.resourceCodes,
				startTimeUsec: e2eRelationConfig.startTimeUsec,
				endTimeUsec: e2eRelationConfig.endTimeUsec,
			};
			currentNode.value = d.nodes[0];
			searchNodeInfo();
			queryNetworkDetail();
			queryNetworkMetaDataDetail();
			ydItRoadRef.value?.setItemStateById(d.nodes[0].id, 'selected', true);
		}
	});
}

// 处理node节点数据
function dealNodeData(detail: NodeConfigType) {
	// 设置指标名称文本和值文本
	let indicatorText = '',
		indicatorValText = '';
	// 最后一端的指标名称文本和值文本
	let lastIndicatorText = '',
		lastIndicatorValText = '';
	if (detail.segmentId === 0) {
		// 客户端
		indicatorText += 'IP端口\n';
		indicatorValText += detail.ipPort + '\n';
		if (detail.requestMac !== null && detail.requestMac !== '') {
			indicatorText += 'Mac\n';
			indicatorValText += detail.requestMac + '\n';
		}
		indicatorText += '请求开始时间\n响应结束时间\n后端处理时长\n状态';
		indicatorValText += detail.startTime + '\n' + detail.endTime + '\n' + toDecimalFormate(detail.dealTime, 'wm') + '\n' + detail.state;
	} else if (detail.oneFlag === 1 || detail.headerFlag === 1) {
		// 首端
		indicatorText += 'IP端口\n';
		indicatorValText += detail.ipPort + '\n';
		if (detail.responseMac !== null && detail.responseMac !== '') {
			indicatorText += 'Mac\n';
			indicatorValText += detail.responseMac + '\n';
		}
		if (detail.serverResponseStartTime !== null && detail.serverResponseStartTime !== '') {
			indicatorText += '服务器响应开始时间\n';
			indicatorValText += detail.serverResponseStartTime + '\n';
		}
		lastIndicatorText += indicatorText;
		lastIndicatorValText += indicatorValText;

		// 最后一端才有请求后端开始时间、后端响应结束时间、后端处理时长
		if (detail.startTime !== null && detail.startTime !== '') {
			indicatorText += '请求后端开始时间\n';
			indicatorValText += detail.startTime + '\n';
		}
		if (detail.endTime !== null && detail.endTime !== '') {
			indicatorText += '后端响应结束时间\n';
			indicatorValText += detail.endTime + '\n';
		}
		if (detail.dealTime !== null) {
			indicatorText += '后端处理时长\n';
			indicatorValText += toDecimalFormate(detail.dealTime, 'wm') + '\n';
		}
		if (detail.serverResponseEndTime !== null && detail.serverResponseEndTime !== '') {
			indicatorText += '服务器响应结束时间\n';
			indicatorValText += detail.serverResponseEndTime + '\n';
			lastIndicatorText += '服务器响应结束时间\n';
			lastIndicatorValText += detail.serverResponseEndTime + '\n';
		}
		if (detail.serverResponseTime !== null) {
			indicatorText += '服务器响应时长\n';
			indicatorValText += toDecimalFormate(detail.serverResponseTime, 'wm') + '\n';
			lastIndicatorText += '服务器响应时长\n';
			lastIndicatorValText += toDecimalFormate(detail.serverResponseTime, 'wm') + '\n';
		}
		indicatorText += '状态';
		indicatorValText += detail.state;
		lastIndicatorText += '状态';
		lastIndicatorValText += detail.state;
	} else if (detail.startTime !== null && detail.startTime !== '') {
		indicatorText += '服务器响应开始时间\n';
		indicatorValText += detail.serverResponseStartTime + '\n';
		lastIndicatorText += indicatorText;
		lastIndicatorValText += indicatorValText;
		// 最后一端才有请求后端开始时间、后端响应结束时间、后端处理时长
		indicatorText += '请求后端开始时间\n后端响应结束时间\n后端处理时长\n';
		indicatorValText += detail.startTime + '\n' + detail.endTime + '\n' + toDecimalFormate(detail.dealTime, 'wm') + '\n';
		indicatorText += '服务器响应结束时间\n响应时长\n健康度\n状态';
		indicatorValText +=
			detail.serverResponseEndTime +
			'\n' +
			toDecimalFormate(detail.serverResponseTime, 'wm') +
			'\n' +
			(detail.successRate === null ? '' : detail.successRate + '%') +
			'\n' +
			detail.state;
		lastIndicatorText += '服务器响应结束时间\n响应时长\n健康度\n状态';
		lastIndicatorValText +=
			detail.serverResponseEndTime +
			'\n' +
			toDecimalFormate(detail.serverResponseTime, 'wm') +
			'\n' +
			(detail.successRate === null ? '' : detail.successRate + '%') +
			'\n' +
			detail.state;
	} else {
		indicatorText += '服务器响应开始时间\n服务器响应结束时间\n响应时长\n健康度\n状态';
		indicatorValText +=
			detail.serverResponseStartTime +
			'\n' +
			detail.serverResponseEndTime +
			'\n' +
			toDecimalFormate(detail.serverResponseTime, 'wm') +
			'\n' +
			(detail.successRate === null ? '' : detail.successRate + '%') +
			'\n' +
			detail.state;
	}

	const result: NodeConfigType = {
		...detail,
		x: detail.locationX,
		y: detail.locationY,
		info: JSON.parse(JSON.stringify(detail)),
		indicatorText: indicatorText,
		indicatorValText: indicatorValText,
		lastIndicatorText: lastIndicatorText,
		lastIndicatorValText: lastIndicatorValText,
	};
	return result;
}

// 获取节点状态
function getNodeStatus(state: string, successRate: any) {
	if (state === '成功') {
		// normal
		return 1;
	} else if (state === '失败') {
		// danger
		return 3;
	} else if (successRate >= 90) {
		// normal
		return 1;
	} else if (successRate >= 70 && successRate < 90) {
		// alarm
		return 2;
	} else if (successRate >= 0 && successRate < 70) {
		// danger
		return 3;
	} else {
		// no-data
		return 0;
	}
}
// 双击端展示详情信息
function dblclickNodeHandler(ev: any) {
	let model: any = ev.item.getModel();
	if (model.info.segmentId == 0 || model.info.headerFlag == 1) {
		// 客户端或首端
		currentHeaderFlag.value = 1;
	} else {
		// 非客户端、非首端
		currentHeaderFlag.value = 0;
	}

	e2eDetail.formData = {
		...e2eDetail.formData,
		dataType: model.info.dataType,
		dataId: model.info.dataId,
		codeList: model.info.resourceCodes,
		startTimeUsec: e2eRelationConfig.startTimeUsec,
		endTimeUsec: e2eRelationConfig.endTimeUsec,
	};
	busiStepTableRef1.value?.toggleRowExpansion(currentRow1.value, false);
	searchNodeInfo();
	queryNetworkDetail();
	queryNetworkMetaDataDetail();
}
// 查询节点详情信息
function searchNodeInfo() {
	e2eDetail.tableConfig.loading = true;
	queryEndToEndDetail(e2eDetail.formData).then((res: ApiResponse) => {
		e2eDetail.tableConfig.loading = false;
		if (res.code !== 0) {
			return;
		}
		e2eDetail.tableData.data = res.data.data;
		// e2eDetail.tableData.total = res.data.total;
		e2eDetail.tableConfig.pagination!.total = res.data.total;
		e2eDetail.tableData.data.forEach((ov: any) => {
			if (!alarmTableData1[ov.id]) {
				alarmTableData1[ov.id] = {
					data: [],
					total: 0,
				};
			}
		});
	});
}

// 请求网络详情接口
function queryNetworkDetail() {
	networkDetailConfig.loading = true;
	let id = currentNode.value.id;
	let params = { ...e2eDetail.formData };
	if (id !== null) {
		params.segmentId = parseInt(id);
	}
	queryNetworkDetailList(params).then((res: ApiResponse) => {
		networkDetailConfig.loading = false;
		if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			return;
		}

		networkDetailData.data = res.data.data;
		networkDetailConfig.pagination!.total = res.data.total;
	});
}

// // 请求网元详情接口
function queryNetworkMetaDataDetail() {
	networkMetaDataDetailConfig.loading = true;
	let params = { ...e2eDetail.formData, systemId: currentStepData.value.systemId };
	let id = currentNode.value.id;
	if (id !== null) {
		params.segmentId = parseInt(id);
	}
	queryNetworkMetaDataDetailList(params).then((res: ApiResponse) => {
		networkMetaDataDetailConfig.loading = false;
		if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			return;
		}

		networkMetaDataDetailData.data = res.data.data;
		networkMetaDataDetailConfig.pagination!.total = res.data.total;
	});
}

// 拖拽端更新坐标
function updateSegmentPos(ev: any, model: any) {
	// 编辑模式启动情况下才更新网端位置
	if (e2eRelationConfig.mode === 'edit' || model) {
		let segmentPos = model || {
			segmentId: ev.item.getModel().id,
			locationX: ev.item.getModel().x,
			locationY: ev.item.getModel().y,
		};
		let dId = e2eRelationConfig.preRelvanceId;
		segmentPos.systemId = dId.substring(0, 4) + dId.substring(dId.length - 5);
		if (segmentPos.locationX) {
			updateSegmentPosition(segmentPos).then((res) => {});
		}
	}
}

// 提包分析
function handlePackageAnalysis(item: any, btnFlag: any) {
	let probeArr = item.probeIp.split(':');
	let tcpOrUdpStr = item.requestIp + ':' + item.requestPort + '_' + item.responseIp + ':' + item.responsePort;
	let userName = btoa('admin');
	let password = btoa('1qazxsw2!@');
	let startTime = parseTime(new Date(item.startTime).getTime() - 1000, '{y}-{m}-{d} {h}:{i}:{s}');
	let endTime = parseTime(new Date(item.endTime).getTime() + 1000, '{y}-{m}-{d} {h}:{i}:{s}');
	getConfigKey('apm.datapacket.analysis').then((res) => {
		let ipPort = res.data;
		if (ipPort) {
			let url = '';
			if (btnFlag === 2) {
				url = 'http://' + ipPort + '/yd-apm-web/api/downloadPacket/downloadStart.action';
			} else {
				url = 'http://' + ipPort + '/yd-apm-web/api/pktAnalysisController/pktAnalysis.action';
			}
			let params = [
				{ name: 'name', value: userName },
				{ name: 'password', value: password },
				{ name: 'beginTime', value: startTime },
				{ name: 'endTime', value: endTime },
				{ name: 'filterType', value: 3 },
				{ name: 'tcpOrUdpList[0].probeIp', value: probeArr[0] },
				{ name: 'tcpOrUdpList[0].probeNum', value: probeArr[1] },
				{ name: 'tcpOrUdpList[0].TcpOrUdpStr', value: tcpOrUdpStr },
			];
			simulateFormSubmit(url, params, '1', 'get');
		} else {
			proxy?.$message.warning('请前往参数配置页面配置提包分析服务器地址');
		}
	});
}
</script>
<style rel="stylesheet/scss" lang="scss">
:deep(.el-table__expand-icon) {
	display: none;
}
:deep(.indicator-count) {
	color: #ff9a0c;
	cursor: pointer;
	text-decoration: underline;
}

.business-detail-container {
	margin: 10px;

	.el-loading-mask {
		background-color: rgba(255, 255, 255, 0.3);
	}
	.el-card__body {
		padding: 15px 20px 35px 20px;
	}
}

.overview-label {
	color: #2beded;
}

.overview-text {
	color: #ffffff;
}

.circle {
	display: inline-block;
	width: 8px;
	height: 8px;
	margin-left: 8px;
	margin-right: 8px;
	background-color: #2beded;
	border-radius: 50%;
	-moz-border-radius: 50%;
	-webkit-border-radius: 50%;
}
.container-bg {
	position: relative;
	background-color: rgba(29, 39, 75, 0.31);
	border-radius: 12px;
	margin-top: 10px;
	width: 100%;
}
.overview-title {
	padding-top: 16px;
	width: 100%;
	display: flex;
	align-items: center;
	.title-label {
		color: #ffffff;
		font-size: 16px;
		font-weight: bold;
	}
}
.overview-box {
	background-color: rgb(42, 80, 125);
	width: 100%;
	padding-bottom: 10px;

	border: 2px solid #2beded;
	.overview-title {
		padding-top: 0;
		height: 48px;
	}
	.overview-row {
		width: 100%;
		margin-left: 20px;
		.overview-label {
			font-size: 14px;
			color: #2beded;
			margin-bottom: 6px;
			float: left;
		}
		.overview-text {
			font-size: 14px;
			color: #ffffff;
		}
	}
}
.chart-box {
	height: 300px;
	width: 100%;
}
</style>
<style scoped lang="scss">
:deep(.el-table__expand-icon) {
	display: none;
}
</style>
